//
// Proba.cpp for 201proba in /home/morel_t//Rendu/maths/201proba
//
// Made by thomas morel
// Login   <morel_t@epitech.net>
//
// Started on  Mon Feb 13 10:22:16 2012 thomas morel
// Last update Mon Feb 13 17:07:53 2012 thomas morel
//

#include <iostream>
#include <algorithm>
#include <sstream>
#include <iomanip>
#include "Proba.hh"

Proba::Proba(const std::string &expression) : result(0), expr(expression), operand(expression)
{
}

Proba::~Proba()
{
}

double	Proba::getResult() const
{
  return (this->result);
}

std::string	Proba::getExpr() const
{
  return (this->expr);
}

void		Proba::replace(char c)
{
  size_t	found;

  found = this->operand.find(c);
  if (found != std::string::npos)
    this->operand.replace(found, 1, " ");
  while (found != std::string::npos)
    {
      found = this->operand.find(c, found+1);
      if (found != std::string::npos)
	this->operand.replace(found, 1, " ");
    }
}

void			Proba::fillOperandList()
{
  double		tmp;
  std::stringstream	stream;

  stream << this->operand;
  for (int n = 0; n <= this->listOperator.size(); n++)
    {
      stream >> tmp;
      listOperand.push_back(tmp);
    }
}

void		Proba::fillOperatorList()
{
  int		i = 0;

  while (i < this->expr.size())
    {
      if (this->expr[i] == '+' || this->expr[i] == 'x')
	listOperator.push_back(this->expr[i]);
      i++;
    }
}

static double	doProba(double number)
{
  double	tmp = number;

  if (tmp < 0)
    tmp *= -1;
  tmp = (((5 * tmp) + 6) / (12 * tmp));
  if (number < 0)
    return (1 - tmp);
  else
    return (tmp);
}

void		Proba::applyProba()
{
  transform(this->listOperand.begin(), this->listOperand.end(), this->listOperand.begin(), doProba);
}

static bool	isIntersectionInside(const std::list<char> &operatorList)
{
  std::list<char>::const_iterator	begin = operatorList.begin();
  std::list<char>::const_iterator	end = operatorList.end();

  for (std::list<char>::const_iterator it = begin; it != end; it++)
    {
      if (*it == 'x')
	return (true);
    }
  return (false);
}

void		Proba::findResult()
{
  double	numberA;
  double	numberB;
  char		op;

  while (this->listOperator.size())
    {
      op = this->listOperator.front();
      this->listOperator.pop_front();
      numberA = this->listOperand.front();
      this->listOperand.pop_front();
      numberB = this->listOperand.front();
      this->listOperand.pop_front();
      if (op == 'x')
	this->listOperand.push_front(numberA * numberB);
      else if (op == '+')
	{
	  if (isIntersectionInside(listOperator))
	    {
	      this->listOperator.push_back(op);
	      this->listOperand.push_back(numberA);
	      this->listOperand.push_front(numberB);
	    }
	  else
	    this->listOperand.push_front(numberA + numberB - (numberA * numberB));
	}
    }
  this->result = this->listOperand.front();
  this->listOperand.pop_front();
}

void		start(const char *expression)
{
  Proba		expr(expression);

  std::cout << "Your expression is \"" << "\033[1;33m"
	    << expr.getExpr() << "\033[0m" << "\"" << std::endl;
  expr.replace('+');
  expr.replace('x');
  expr.fillOperatorList();
  expr.fillOperandList();
  expr.applyProba();
  expr.findResult();
  std::cout << "The probality to sell his computer is " << "\033[1;31m"
	    << std::setprecision (3) << expr.getResult() << "\033[0m"
	    << " with this expression." << std::endl;
}
